using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections.Specialized;
using System.Globalization;
using System.Threading;
using System.Data;
using System.Runtime.Remoting.Contexts;
using System.Runtime.CompilerServices;

namespace Infrastructure.CrossCutting.Resource
{
    /// <summary>
    /// Data access component for the StringResources table. 
    /// This type is thread safe.
    /// </summary>
    public class DBResources : IDisposable
    {
        private const string DefaultResourceCulture = "en";
        private string _resourceType = "";

        /// <summary>
        /// Constructs this instance of the data access 
        /// component supplying a resource type for the instance. 
        /// </summary>
        /// <param name="resourceType">The resource type.</param>
        public DBResources(string resourceType)
        {
            // save the resource type for this instance
            this._resourceType = resourceType;
            //add database connect
        }

        /// <summary>
        /// Uses an open database connection to recurse 
        /// looking for the resource.
        /// Retrieves a resource entry based on the 
        /// specified culture and resource 
        /// key. The resource type is based on this instance of the
        /// StringResourceDALC as passed to the constructor.
        /// Resource fallback follows the same mechanism 
        /// of the .NET 
        /// ResourceManager. Ultimately falling back to the 
        /// default resource
        /// specified in this class.
        /// </summary>
        /// <param name="culture">The culture to search with.</param>
        /// <param name="resourceKey">The resource key to find.</param>
        /// <returns>If found, the resource string is returned. 
        /// Otherwise an empty string is returned.</returns>
        private string GetResourceByCultureAndKeyInternal(CultureInfo culture, string resourceKey)
        {
            // we should only get one back, but just in case, we'll iterate reader results
            var resources = new StringCollection();
            string resourceValue = null;
            //culture.Name resourceKey
            //resources.Add()
            // we should only get 1 back, this is just to verify the tables aren't incorrect
            if (resources.Count == 0)
            {
                // is this already fallback location?
                if (culture.Name == DefaultResourceCulture)
                {
                    throw new InvalidOperationException(resourceKey);
                }

                // try to get parent culture
                culture = culture.Parent;
                if (culture.Name.Length == 0)
                {
                    // there isn't a parent culture, change to neutral
                    culture = new CultureInfo(DefaultResourceCulture);
                }
                resourceValue = this.GetResourceByCultureAndKeyInternal(culture, resourceKey);
            }
            else if (resources.Count == 1)
            {
                resourceValue = resources[0];
            }
            else
            {
                // if > 1 row returned, log an error, we shouldn't have > 1 value for a resourceKey!
                throw new DataException(resourceKey);
            }

            return resourceValue;
        }

        /// <summary>
        /// Returns a dictionary type containing all resources for a 
        /// particular resource type and culture.
        /// The resource type is based on this instance of the
        /// StringResourceDALC as passed to the constructor.
        /// </summary>
        /// <param name="culture">The culture to search for.</param>
        /// <returns>If found, the dictionary contains key/value 
        /// pairs for each 
        /// resource for the specified culture.</returns>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public ListDictionary GetResourcesByCulture(CultureInfo culture)
        {
            // make sure we have a default culture at least
            if (culture == null || culture.Name.Length == 0)
            {
                culture = new CultureInfo(DefaultResourceCulture);
            }

            // create the dictionary
            var resourceDictionary = new ListDictionary();
            try
            {
                // get resources from the database
                //culture.Name
                //resourceDictionary.Add(k, v);

            }
            finally
            {

            }
            // TODO: check dispose results
            return resourceDictionary;
        }

        /// <summary>
        /// Retrieves a resource entry based on the specified culture and 
        /// resource key. The resource type is based on this instance of the
        /// StringResourceDALC as passed to the constructor.
        /// To optimize performance, this function opens the database connection 
        /// before calling the internal recursive function. 
        /// </summary>
        /// <param name="culture">The culture to search with.</param>
        /// <param name="resourceKey">The resource key to find.</param>
        /// <returns>If found, the resource string is returned. Otherwise an empty string is returned.</returns>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public string GetResourceByCultureAndKey(CultureInfo culture, string resourceKey)
        {
            string resourceValue;
            try
            {
                // make sure we have a default culture at least
                if (culture == null || culture.Name.Length == 0)
                {
                    culture = new CultureInfo(DefaultResourceCulture);
                }

                // recurse to find resource, includes fallback behavior
                resourceValue = this.GetResourceByCultureAndKeyInternal(culture, resourceKey);
            }
            finally
            {

            }
            return resourceValue;
        }

        #region IDisposable Members

        public void Dispose()
        {

        }

        #endregion
    }

    public class ResourceRecord
    {
        public string ResourceType { get; set; }
        public string CultureCode { get; set; }
        public string ResourceKey { get; set; }
        public string ResourceValue { get; set; }
    }
}
